<template>
  <div class="wh-form-container">
    <div class="wh-form-left">
      <el-scrollbar class="left-scrollbar">
        <div class="components-list">
          <div class="components-title">
            <svg-icon icon-class="component" />输入型组件
          </div>
          <draggable
            class="components-draggable"
            :list="inputComponents"
            :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
            :clone="cloneComponent"
            draggable=".components-item"
            :sort="false"
            @end="onEnd"
          >
            <div
              v-for="(element, index) in inputComponents" :key="index" class="components-item"
              @click="addComponent(element)"
            >
              <div class="components-body">
                <svg-icon :icon-class="element.tagIcon" />
                {{ element.label }}
              </div>
            </div>
          </draggable>
          <div class="components-title">
            <svg-icon icon-class="component" />选择型组件
          </div>
          <draggable
            class="components-draggable"
            :list="selectComponents"
            :group="{ name: 'componentsGroup', pull: 'clone', put: false }"
            :clone="cloneComponent"
            draggable=".components-item"
            :sort="false"
            @end="onEnd"
          >
            <div
              v-for="(element, index) in selectComponents"
              :key="index"
              class="components-item"
              @click="addComponent(element)"
            >
              <div class="components-body">
                <svg-icon :icon-class="element.tagIcon" />
                {{ element.label }}
              </div>
            </div>
          </draggable>
          <div class="components-title">
            <svg-icon icon-class="component" /> 布局型组件
          </div>
          <draggable
            class="components-draggable" :list="layoutComponents"
            :group="{ name: 'componentsGroup', pull: 'clone', put: false }" :clone="cloneComponent"
            draggable=".components-item" :sort="false" @end="onEnd"
          >
            <div
              v-for="(element, index) in layoutComponents" :key="index" class="components-item"
              @click="addComponent(element)"
            >
              <div class="components-body">
                <svg-icon :icon-class="element.tagIcon" />
                {{ element.label }}
              </div>
            </div>
          </draggable>
        </div>
      </el-scrollbar>
    </div>
    <div class="wh-form-content">
      <div class="action-bar">
        <el-button icon="el-icon-download" type="text" @click="download">
          导出vue文件
        </el-button>
        <el-button class="copy-btn-main" icon="el-icon-document-copy" type="text" @click="copy">
          复制代码
        </el-button>
        <el-button class="delete-btn" icon="el-icon-delete" type="text" @click="empty">
          清空
        </el-button>
      </div>
      <el-scrollbar class="center-scrollbar">
        <el-row class="center-board-row" :gutter="formConf.gutter">
          <el-form
            :size="formConf.size"
            :label-position="formConf.labelPosition"
            :disabled="formConf.disabled"
            :label-width="formConf.labelWidth + 'px'"
          >
            <draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup">
              <draggable-item
                v-for="(element, index) in drawingList"
                :key="element.renderKey"
                :drawing-list="drawingList"
                :element="element"
                :index="index"
                :active-id="activeId"
                :form-conf="formConf"
                @activeItem="activeFormItem"
                @copyItem="drawingItemCopy"
                @deleteItem="drawingItemDelete"
              />
            </draggable>
            <div v-show="!drawingList.length" class="empty-info">
              从左侧拖入或点选组件进行表单设计
            </div>
          </el-form>
        </el-row>
      </el-scrollbar>
    </div>
    <right-panel
      :active-data="activeData"
      :form-conf="formConf"
      :show-field="!!drawingList.length"
      @tag-change="tagChange"
    />
  </div>
</template>

<script>
import SvgIcon from './components/SvgIcon'
import Draggable from 'vuedraggable'
import { inputComponents, selectComponents, layoutComponents, formConf } from './utils/config'
import drawingDefault from './utils/drawingDefault'
import DraggableItem from './components/DraggableItem'
import RightPanel from './components/RightPanel'
let oldActiveId
let tempActiveData

export default {
  components: {
    SvgIcon,
    Draggable,
    DraggableItem,
    RightPanel
  },
  data() {
    return {
      formConf,
      idGlobal: 100,
      inputComponents,
      selectComponents,
      layoutComponents,
      activeData: drawingDefault[0],
      activeId: drawingDefault[0].formId,
      dialogVisible: false,
      generateConf: null,
      showFileName: false,
      drawingList: drawingDefault,
    }
  },
  methods: {
    activeFormItem(element) {
      this.activeData = element
      this.activeId = element.formId
    },
    onEnd (obj, a) {
      if (obj.from !== obj.to) {
        this.activeData = tempActiveData
        this.activeId = this.idGlobal
      }
    },
    addComponent(item) {
      const clone = this.cloneComponent(item)
      this.drawingList.push(clone)
      this.activeFormItem(clone)
    },
    cloneComponent(origin) {
      const clone = JSON.parse(JSON.stringify(origin))
      clone.formId = ++this.idGlobal
      clone.span = formConf.span
      clone.renderKey = +new Date() // 改变renderKey后可以实现强制更新组件
      if (!clone.layout) clone.layout = 'colFormItem'
      if (clone.layout === 'colFormItem') {
        clone.vModel = `field${this.idGlobal}`
        clone.placeholder !== undefined && (clone.placeholder += clone.label)
        tempActiveData = clone
      } else if (clone.layout === 'rowFormItem') {
        delete clone.label
        clone.componentName = `row${this.idGlobal}`
        clone.gutter = this.formConf.gutter
        tempActiveData = clone
      }
      return tempActiveData
    },
    download() {
      this.dialogVisible = true
      this.showFileName = true
      this.operationType = 'download'
    },
    copy() {
      this.dialogVisible = true
      this.showFileName = false
      this.operationType = 'copy'
    },
    empty() {
      this.$confirm('确定要清空所有组件吗？', '提示', { type: 'warning' }).then(
        () => {
          this.drawingList = []
        }
      )
    },
    drawingItemCopy(item, parent) {
      let clone = JSON.parse(JSON.stringify(item))
      clone = this.createIdAndKey(clone)
      parent.push(clone)
      this.activeFormItem(clone)
    },
    createIdAndKey(item) {
      item.formId = ++this.idGlobal
      item.renderKey = +new Date()
      if (item.layout === 'colFormItem') {
        item.vModel = `field${this.idGlobal}`
      } else if (item.layout === 'rowFormItem') {
        item.componentName = `row${this.idGlobal}`
      }
      if (Array.isArray(item.children)) {
        item.children = item.children.map(childItem => this.createIdAndKey(childItem))
      }
      return item
    },
    drawingItemDelete(index, parent) {
      parent.splice(index, 1)
      this.$nextTick(() => {
        const len = this.drawingList.length
        if (len) {
          this.activeFormItem(this.drawingList[len - 1])
        }
      })
    },
    tagChange(newTag) {
      newTag = this.cloneComponent(newTag)
      newTag.vModel = this.activeData.vModel
      newTag.formId = this.activeId
      newTag.span = this.activeData.span
      delete this.activeData.tag
      delete this.activeData.tagIcon
      delete this.activeData.document
      Object.keys(newTag).forEach(key => {
        if (this.activeData[key] !== undefined
          && typeof this.activeData[key] === typeof newTag[key]) {
          newTag[key] = this.activeData[key]
        }
      })
      this.activeData = newTag
      this.updateDrawingList(newTag, this.drawingList)
    },
    updateDrawingList(newTag, list) {
      const index = list.findIndex(item => item.formId === this.activeId)
      if (index > -1) {
        list.splice(index, 1, newTag)
      } else {
        list.forEach(item => {
          if (Array.isArray(item.children)) this.updateDrawingList(newTag, item.children)
        })
      }
    }
  },
}
</script>

<style scoped lang="scss">
  $selectedColor: #f6f7ff;
  $lighterBlue: #409EFF;
  .wh-form-container {
    position: relative;
    width: 100%;
    height: 100%;
    min-height: 500px;
    .wh-form-left {
      width: 260px;
      position: absolute;
      left: 0;
      top: 0;
      height: 100%;
      .left-scrollbar .el-scrollbar__wrap {
        box-sizing: border-box;
        overflow-x: hidden !important;
        margin-bottom: 0 !important;
      }
      .components-list {
        padding: 8px;
        box-sizing: border-box;
        height: 100%;
        .components-item {
          display: inline-block;
          width: 48%;
          margin: 1%;
          transition: transform 0ms !important;
        }
        .components-draggable{
          padding-bottom: 20px;
        }
        .components-title{
          font-size: 14px;
          color: #222;
          margin: 6px 2px;
          .svg-icon{
            color: #666;
            font-size: 18px;
          }
        }

        .components-body {
          padding: 8px 10px;
          background: $selectedColor;
          font-size: 12px;
          cursor: move;
          border: 1px dashed $selectedColor;
          border-radius: 3px;
          .svg-icon{
            color: #777;
            font-size: 15px;
          }
          &:hover {
            border: 1px dashed #787be8;
            color: #787be8;
            .svg-icon {
              color: #787be8;
            }
          }
        }

      }
    }
    .wh-form-content {
      height: 100%;
      width: auto;
      margin: 0 350px 0 260px;
      box-sizing: border-box;
      .empty-info{
        position: absolute;
        top: 46%;
        left: 0;
        right: 0;
        text-align: center;
        font-size: 18px;
        color: #ccb1ea;
        letter-spacing: 4px;
      }
      ::v-deep .action-bar{
        & .el-button+.el-button {
          margin-left: 15px;
        }
        & i {
          font-size: 20px;
          vertical-align: middle;
          position: relative;
          top: -1px;
        }
      }

      .center-scrollbar {
        height: calc(100% - 42px);
        overflow: hidden;
        border-left: 1px solid #f1e8e8;
        border-right: 1px solid #f1e8e8;
        box-sizing: border-box;

      }
    }
  }


  .center-board-row {
    padding: 12px 12px 15px 12px;
    box-sizing: border-box;
    & > .el-form {
      // 69 = 12+15+42
      height: calc(100% - 69px);
    }
  }
  .drawing-board {
    height: 100%;
    position: relative;
    .components-body {
      padding: 0;
      margin: 0;
      font-size: 0;
    }
    .sortable-ghost {
      position: relative;
      display: block;
      overflow: hidden;
      &::before {
        content: " ";
        position: absolute;
        left: 0;
        right: 0;
        top: 0;
        height: 3px;
        background: rgb(89, 89, 223);
        z-index: 2;
      }
    }
    .components-item.sortable-ghost {
      width: 100%;
      height: 60px;
      background-color: $selectedColor;
    }
    .active-from-item {
      & > .el-form-item{
        background: $selectedColor;
        border-radius: 6px;
      }
      & > .drawing-item-copy, & > .drawing-item-delete{
        display: initial;
      }
      & > .component-name{
        color: $lighterBlue;
      }
    }
    .el-form-item{
      margin-bottom: 15px;
    }
  }
  ::v-deep .drawing-item{
    position: relative;
    cursor: move;
    &.unfocus-bordered:not(.activeFromItem) > div:first-child  {
      border: 1px dashed #ccc;
    }
    .el-form-item{
      padding: 12px 10px;
    }
  }
  ::v-deep .drawing-row-item{
    position: relative;
    cursor: move;
    box-sizing: border-box;
    border: 1px dashed #ccc;
    border-radius: 3px;
    padding: 0 2px;
    margin-bottom: 15px;
    .drawing-row-item {
      margin-bottom: 2px;
    }
    .el-col{
      margin-top: 22px;
    }
    .el-form-item{
      margin-bottom: 0;
    }
    .drag-wrapper{
      min-height: 80px;
    }
    &.active-from-item{
      border: 1px dashed $lighterBlue;
    }
    .component-name{
      position: absolute;
      top: 0;
      left: 0;
      font-size: 12px;
      color: #bbb;
      display: inline-block;
      padding: 0 6px;
    }
  }
  ::v-deep .drawing-item,
  ::v-deep .drawing-row-item{
    &:hover {
      & > .el-form-item{
        background: $selectedColor;
        border-radius: 6px;
      }
      & > .drawing-item-copy, & > .drawing-item-delete{
        display: initial;
      }
    }
    & > .drawing-item-copy, & > .drawing-item-delete{
      display: none;
      position: absolute;
      top: -10px;
      width: 22px;
      height: 22px;
      line-height: 22px;
      text-align: center;
      border-radius: 50%;
      font-size: 12px;
      border: 1px solid;
      cursor: pointer;
      z-index: 1;
    }
    & > .drawing-item-copy{
      right: 56px;
      border-color: $lighterBlue;
      color: $lighterBlue;
      background: #fff;
      &:hover{
        background: $lighterBlue;
        color: #fff;
      }
    }
    & > .drawing-item-delete{
      right: 24px;
      border-color: #F56C6C;
      color: #F56C6C;
      background: #fff;
      &:hover{
        background: #F56C6C;
        color: #fff;
      }
    }
  }
</style>
